home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / idle / idleout-.tar / idleout-mcm.tar / autologout.c next >
C/C++ Source or Header  |  1994-10-15  |  7KB  |  178 lines

  1. /*
  2.         "@(#) autologout.c by David Dickson" 
  3.         Modified by Michael C. Mitchell, 15Oct94
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. */
  20. #include    <stdio.h>
  21. #include    <signal.h>
  22. #include    <string.h>
  23. #include    <sys/types.h>
  24. #include    <sys/stat.h>
  25. #include    <utmp.h>
  26. #define     GRACE       60  /* grace time (sec) for user reply */
  27. #define     KWAIT       20  /* time to wait after kill (in sec.) */
  28. #define     WARNING     1   /* a warning message */
  29. #define     LOGOFF      2   /* a log-off message */
  30. #define     NOLOGOFF    3   /* a log-off failure message */
  31. #define     SEC         60  /* seconds per minute */
  32. #define     TIMEMAX     10  /* maximum idle time (minutes) */
  33.  
  34. struct utmp *utmpp;         /* pointer to utmp file entry */
  35. char        *ctime();       /* returns pointer to time string */
  36. struct utmp *getutent();    /* returns next utmp file entry */
  37.  
  38.  
  39. main()
  40. {
  41.     if (fork())             /* the parent process */
  42.         exit(0);            /* exits */
  43.     /* the child processes all utmp file entries: */
  44.     while ((utmpp = getutent()) != (struct utmp *) NULL)
  45.         check_idle();
  46.     exit(0);    /* done, so bye */
  47. }
  48.  
  49. check_idle()    /* select utmp entries older than TIMEMAX */
  50. {
  51.     char        dev[24], name[12];
  52.     struct stat status, *pstat;
  53.     time_t      idle, pres_time, start, time();
  54.     FILE *in_file;
  55.     char in_name[8];
  56.  
  57.     pstat = &status;    /* point to status structure */
  58.     if (utmpp->ut_type != USER_PROCESS) /* if not user process */
  59.         return(0);                      /* skip the utmp entry */
  60.     strcpy(dev, "/dev/");   /* add "/dev/" directory prefix */
  61.     strcat(dev, utmpp->ut_line);    /* append basename of port */
  62.     if (stat(dev, pstat))   /* if can't get status for port */
  63.         bailout("can't get status of user's terminal", 1);
  64.     pres_time = time((time_t *)0);  /* get current time */
  65.     /* idle time is current time less last access time: */
  66.     idle = (pres_time - pstat->st_atime) / SEC;
  67.     if (idle < TIMEMAX)     /* if user was recently active */
  68.         return(0);          /* ignore this utmp entry */
  69.     strncpy(name, utmpp->ut_user, 8);   /* else get user name */
  70.     name[8] = '\0';          /* null terminate user name string */
  71.     
  72.     /* mcm 15Oct94 */
  73.     if ( (in_file=fopen("/etc/autologout.exempt", "r")) != NULL)
  74.     {
  75.       while (fscanf(in_file, "%s", in_name) != EOF)
  76.       {
  77.         if (!strcmp(name,in_name))
  78.         {
  79.           fclose(in_file);
  80.           return(0);  /* user exempt */
  81.         }
  82.       }
  83.       fclose(in_file);
  84.     }
  85.     
  86.     /* mcm 15Oct94 */
  87.     
  88.     mesg(WARNING, name, dev, (int)idle); /* send warning to user */
  89.     if (stat(dev, pstat))
  90.         bailout("can't get status of user's terminal", 2);
  91.     start = pstat->st_atime;    /* start time for countdown */
  92.     sleep(GRACE);
  93.     if (stat(dev, pstat))
  94.         bailout("can't get status of user's terminal", 3);
  95.     if (start < pstat->st_atime)    /* user did something */
  96.         return(0);
  97.     else {  /* user abandoned terminal */
  98.         if (!killit(utmpp->ut_pid))
  99.             mesg(NOLOGOFF, name, dev, (int)idle); /* couldn't kill */
  100.         else
  101.             mesg(LOGOFF, name, dev, (int)idle); /* okay */
  102.         return(0);
  103.     }
  104. }
  105.  
  106. mesg(flag, name, dev, idle) /* mail to user and log message */
  107. int     flag, idle;     /* flag indicates message type */
  108. char    *name, *dev;
  109. {
  110.     char    mbuf[256];  /* message buffer */
  111.     time_t  tvec;
  112.     FILE    *fopen(), *fp, *log, *mprog;
  113.  
  114.     time(&tvec);    /* store time in tvec */
  115.     if ((log = fopen("/usr/adm/logoutlog", "a")) == (FILE *) NULL)
  116.         bailout("can't open log file", 4);
  117.     if (flag == WARNING) {  /* process warning message */
  118.         if ((fp = fopen(dev, "w")) == (FILE *) NULL)
  119.             bailout("can't open user's terminal", 5);
  120.         fprintf(fp,
  121.             "%s: You've been idle for %d min.\07\n", name, idle);
  122.         fprintf(fp,
  123.             "you'll be logged off in 60 sec. unless you hit return:");
  124.         fclose(fp);
  125.         fprintf(log, "** WARNING ** %s %s (%d min idle time) %s",
  126.             name, dev+5, idle, ctime(&tvec)+3);
  127.     }
  128.     if (flag == LOGOFF) {   /* process log-off message */
  129.         fprintf(log, "** LOGOFF ** %s %s (%d min idle time) %s",
  130.             name, dev + 5, idle, ctime(&tvec) + 3);
  131.         sprintf(mbuf, "/bin/mail %s", name);
  132.         /* open pipe to mail program for writing */
  133.         if ((mprog = popen(mbuf, "w")) == (FILE *) NULL)
  134.             bailout("can't use /bin/mail program", 6);
  135.         fprintf(mprog, "Subject: Excess Idle Time\nLogged \
  136. off - excess idle time - %s %s\ntty = %s\n",
  137.             name, ctime(&tvec), dev + 5);
  138.         fclose(mprog);
  139.     }
  140.     if (flag == NOLOGOFF) {  /* send mail to root if can't kill */
  141.         fprintf(log, "** LOGOFF-FAIL ** %s (pid = %d) \
  142. %s (%d min idle time) %s",
  143.             name, utmpp->ut_pid, dev+5, idle, ctime(&tvec)+3);
  144.         sprintf(mbuf, "/bin/mail root");
  145.         if ((mprog = popen(mbuf, "w")) == (FILE *) NULL)
  146.             bailout("can't use /bin/mail program", 7);
  147.         fprintf(mprog, "Subject: Can't logoff %s\nCan't Log off \
  148. - %s %s\ntty = %s\n", name, name, ctime(&tvec), dev+5);
  149.         fclose(mprog);
  150.     }
  151.     fclose(log);
  152.     return(0);
  153. }
  154.  
  155. killit(pid) /* terminate process using SIGHUP, then SIGKILL */
  156. int pid;
  157. {
  158.     kill(pid, SIGHUP);  /* first send "hangup" signal */
  159.     sleep(KWAIT);
  160.     if (!kill(pid, 0)) {    /* SIGHUP might be ignored */
  161.         kill(pid, SIGKILL); /* then send sure "kill" signal */
  162.         sleep(KWAIT);
  163.         if (!kill(pid, 0))
  164.             return(0);  /* failure--refuses to die! */
  165.         else
  166.             return(1);  /* successful kill with SIGKILL */
  167.     } else
  168.         return(1);  /* successful kill with SIGHUP */
  169. }
  170.  
  171. bailout(message, status) /* display error message and exit */
  172. int     status;     /* exit status */
  173. char    *message;   /* pointer to the error message */
  174. {
  175.     fprintf(stderr, "autologout: %s\n", message);
  176.     exit(status);
  177. }
  178.